home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / C / Code Resources / Jims CDEFs 1.50 / demo Source ƒ / utilities / dimText.c < prev    next >
Encoding:
Text File  |  1995-10-27  |  10.8 KB  |  413 lines  |  [TEXT/KAHL]

  1. //----------------------------------------------------------------------------------
  2. //    File        : dimText.c
  3. //    Date        : March 17, 1994
  4. //    Author        : James W. Walker
  5. //                :
  6. //                : renamed routines for consistency with coding style in daAssist.c
  7. //                :  Jim Stout (with apologies to JWW…)
  8. //                :
  9. //                : added some subtle 3D shading of editText items.  5/5/95 jgs
  10. //----------------------------------------------------------------------------------
  11. #include <GestaltEqu.h>
  12. #include "dimText.h"
  13.  
  14. static pascal void dimTextProc( short byteCnt, Ptr textAddr,
  15.         Point numerPt, Point denomPt );
  16.  
  17. static short getRectDepth(Rect *r);
  18.  
  19. /*    ---------------------------------------------------------------------
  20.     dimText.c            This is a group of routines for dimming text
  21.                         items in dialogs.  As is, it assumes that you are
  22.                         not using the dialog's refCon for anything else,
  23.                         and that you are not using the QuickDraw
  24.                         bottlenecks for anything else.
  25.     
  26.     This code can be used freely.  I ask that you tell me about any
  27.     improvements that you think of.
  28.     
  29.     James W. Walker        March 17, 1994
  30.     JWWalker@AOL.com
  31.     76367,2271@compuserve.com
  32.     ---------------------------------------------------------------------
  33. */
  34.  
  35. #define        SYSTEM_6_COMPATIBLE        1
  36.  
  37. typedef struct Dim_list_el {
  38.     short                item_num;
  39.     struct Dim_list_el    *next;
  40.     Rect                bounds;
  41.     Boolean                dim;
  42.     Boolean                editable;
  43. } Dim_list_el;
  44.  
  45. typedef struct {
  46.     Dim_list_el    *dim_list;
  47.     QDTextUPP    Old_text_proc;
  48. #ifdef SYSTEM_6_COMPATIBLE
  49.     Boolean        has_gray_text;
  50.     Boolean        has_CountDITL;
  51. #endif
  52. } Dim_data;
  53.  
  54.  
  55. /*    ---------------------------------------------------------------------
  56.     getDimData        Macro to get the list head.
  57.                         Just used to encapsulate the use of the refCon,
  58.                         so that if you need to store the list head
  59.                         somewhere else you will only need to change this
  60.                         and initDimText.
  61.     ---------------------------------------------------------------------
  62. */
  63. #define    getDimData( dp )        ((Dim_data *) ((WindowPeek)dp)->refCon)
  64.  
  65.  
  66. /*    ---------------------------------------------------------------------
  67.     initDimText        Set up a dialog for dimming text.  Call it once, soon
  68.                     after creating the dialog.
  69.     ---------------------------------------------------------------------
  70. */
  71. void initDimText( DialogPtr dp )
  72. {
  73.     Dim_data    *dim_data_p;
  74.     QDProcs        *qd_procs;
  75.     long        val;
  76.     
  77.     dim_data_p = (Dim_data *) NewPtrClear( sizeof(Dim_data) );
  78.     if (dim_data_p)
  79.     {
  80.         // Store the pointer where we can find it later
  81.         ((WindowPeek)dp)->refCon = (long) dim_data_p;
  82.         
  83.         // Patch the QuickDraw bottleneck for text
  84.         if ( (dp->portBits.rowBytes & 0x8000) == 0 )    // B&W port
  85.         {
  86.             qd_procs = (QDProcs *) NewPtrSysClear( sizeof(QDProcs) );
  87.             SetStdProcs( qd_procs );
  88.         }
  89.         else    // color port
  90.         {
  91.             qd_procs = (QDProcs *) NewPtrSysClear( sizeof(CQDProcs) );
  92.             SetStdCProcs( (CQDProcs *) qd_procs );
  93.         }
  94.         dim_data_p->Old_text_proc = qd_procs->textProc;
  95.         qd_procs->textProc = NewQDTextProc( dimTextProc );
  96.         dp->grafProcs = qd_procs;
  97.         
  98. #if SYSTEM_6_COMPATIBLE
  99.         // Which System 7 features are available?
  100.         dim_data_p->has_gray_text =
  101.             (Gestalt( gestaltQuickdrawFeatures, &val ) == noErr)
  102.             && ( (val & (1L << gestaltHasGrayishTextOr)) != 0 );
  103.         dim_data_p->has_CountDITL =
  104.             (Gestalt( gestaltDITLExtAttr, &val ) == noErr)
  105.             && ( (val & (1L << gestaltDITLExtPresent)) != 0 );
  106. #endif        
  107.  
  108.         makeDimmable( dp );
  109.     }
  110. }
  111.  
  112. /*    ---------------------------------------------------------------------
  113.     disposeDimText        Called once after you are through with a dialog.
  114.     ---------------------------------------------------------------------
  115. */
  116. void disposeDimText( DialogPtr dp )
  117. {
  118.     Ptr        maybe_null;
  119.     
  120.     disposeDimData( dp );
  121.     maybe_null = (Ptr) getDimData(dp);
  122.     if (maybe_null)
  123.         DisposePtr( maybe_null );
  124.     if (dp->grafProcs)
  125.     {
  126.         DisposeRoutineDescriptor( (dp->grafProcs)->textProc );
  127.     }
  128.     dp->grafProcs = NULL;
  129. }
  130.  
  131. /*    ---------------------------------------------------------------------
  132.     dimText        Set the dimming state of a text item.
  133.     ---------------------------------------------------------------------
  134. */
  135. void dimText( DialogPtr dp, short item, Boolean dim )
  136. {
  137.     Dim_data    *dim_head;
  138.     Dim_list_el    *dimmable;
  139.     Rect        iRect;
  140.     Handle        iHandle;
  141.     short        iType;
  142.     short        disable_flag;
  143.     
  144.     dim_head = getDimData(dp);
  145.     if (dim_head != NULL)
  146.     {
  147.         dimmable = dim_head->dim_list;
  148.         // Try to find the right item number in the list.
  149.         while ( (dimmable != NULL) && (dimmable->item_num != item) )
  150.         {
  151.             dimmable = dimmable->next;
  152.         }
  153.         if (dimmable != NULL)    // found it...
  154.         {
  155.             dimmable->dim = dim;
  156.             GetDItem( dp, item, &iType, &iHandle, &iRect );
  157.             if (dimmable->editable)
  158.             {
  159.                 /*
  160.                     To dim an editable text item, we need to turn it
  161.                     into a static text item, and also take some care
  162.                     that it is not showing the insertion point or a
  163.                     selection range.
  164.                 */
  165.                 disable_flag = iType & itemDisable;
  166.                 if (dim)
  167.                 {
  168.                     TEDeactivate( ((DialogPeek) dp)->textH );
  169.                     if (item == ((DialogPeek) dp)->editField + 1 )
  170.                     {
  171.                         SelIText( dp, item, 0, 0 );
  172.                         ((DialogPeek) dp)->editField = -1;
  173.                     }
  174.                     SetDItem( dp, item, statText | disable_flag,
  175.                         iHandle, &iRect );
  176.                     ((DialogPeek) dp)->editField = -1;
  177.                     TEActivate( ((DialogPeek) dp)->textH );
  178.                     InvalRect( &iRect );
  179.                 }
  180.                 else
  181.                 {
  182.                     SetDItem( dp, item, editText | disable_flag,
  183.                         iHandle, &iRect );
  184.                     SelIText( dp, item, 0, 0 );
  185.                     EraseRect( &iRect );
  186.                     TEUpdate( &iRect, ((DialogPeek) dp)->textH );
  187.                 }
  188.             }
  189.             else
  190.             {
  191.                 InvalRect( &iRect );
  192.             }
  193.         }
  194.     }
  195. }
  196.  
  197.  
  198. /*    ---------------------------------------------------------------------
  199.     disposeDimData            Dispose of the individual dimming items.
  200.                             This is called by disposeDimText, so you will
  201.                             not ordinarily have to call it directly
  202.                             unless you are changing item lists
  203.                             dynamically using ShortenDITL and AppendDITL.
  204.     ---------------------------------------------------------------------
  205. */
  206. void disposeDimData( DialogPtr dp )
  207. {
  208.     Dim_data    *dim_head;
  209.     Dim_list_el    *next;
  210.     Rect        r;
  211.     
  212.     dim_head = getDimData(dp);
  213.     while (dim_head->dim_list != NULL)
  214.     {
  215.         r = dim_head->dim_list->bounds;
  216.         InsetRect(&r, -1, -1);                            // jgs 3D shadow
  217.         if(dim_head->dim_list->editable)                // jgs 10/15
  218.             EraseRect( &r );                            // was just EraseRect
  219.         else                                            // added InvalRect
  220.             InvalRect( &r );
  221.         next = dim_head->dim_list->next;
  222.         DisposePtr( (Ptr) dim_head->dim_list );
  223.         dim_head->dim_list = next;
  224.     }
  225. }
  226.  
  227. /*    ---------------------------------------------------------------------
  228.     makeDimmable            Makes all text items in the dialog dimmable,
  229.                             both static and editable text.  Called by
  230.                             initDimText(), so you would not normally need
  231.                             to call it directly.
  232.                             But if you change the item list using
  233.                             ShortenDITL and AppendDITL, you would call
  234.                             disposeDimData() before the change and call
  235.                             makeDimmable() after the change.
  236.     ---------------------------------------------------------------------
  237. */
  238. void makeDimmable( DialogPtr dp )
  239. {
  240.     Dim_data    *dim_head;
  241.     Dim_list_el    *new_dim;
  242.     Rect        iRect;
  243.     Handle        iHandle;
  244.     short        iType, item, max_item;
  245.     
  246.     dim_head = getDimData(dp);
  247.     if (dim_head != NULL)
  248.     {
  249. #if SYSTEM_6_COMPATIBLE
  250.         if (dim_head->has_CountDITL)
  251.         {
  252.             max_item = CountDITL( dp );
  253.         }
  254.         else
  255.         {
  256.             max_item = (**(short **) (((DialogPeek) dp)->items)) + 1;
  257.         }
  258. #else
  259.         max_item = CountDITL( dp );
  260. #endif
  261.         
  262.         for (item = max_item; item > 0; --item)
  263.         {
  264.             GetDItem( dp, item, &iType, &iHandle, &iRect );
  265.             if ( (iType & (statText | editText)) != 0 )
  266.             {
  267.                 new_dim = (Dim_list_el *) 
  268.                     NewPtrClear( sizeof(Dim_list_el) );
  269.                 if (new_dim)
  270.                 {
  271.                     new_dim->next = dim_head->dim_list;
  272.                     dim_head->dim_list = new_dim;
  273.                     new_dim->item_num = item;
  274.                     new_dim->editable = (iType & editText) != 0;
  275.                     new_dim->bounds = iRect;
  276.                     if (new_dim->editable)
  277.                     {
  278.                         InsetRect( &new_dim->bounds, -3, -3 );
  279.                     }
  280.                 }
  281.             }
  282.         }
  283.     }
  284. }
  285.  
  286.  
  287. /*    ---------------------------------------------------------------------
  288.     dimTextProc                The QuickDraw bottleneck routine that does
  289.                             the actual dimming, and also draws the frame
  290.                             around dimmed editable text.
  291.     ---------------------------------------------------------------------
  292. */
  293. static pascal void dimTextProc( short byteCnt, Ptr textAddr,
  294.         Point numerPt, Point denomPt )
  295. {
  296.     short            item_num;
  297.     DialogPtr        dp;
  298.     Dim_list_el        *dimmable;
  299.     Dim_data        *dim_head;
  300.     Rect            gray_rect;
  301.     RgnHandle        save_clip;
  302.     PenState        save_pen;
  303.     RGBColor        saveFore, rgbA = {0xaaaa,0xaaaa,0xaaaa};
  304.     Rect            r;
  305.     
  306.     GetPort( &dp );
  307.     GetPenState( &save_pen );                // jgs added 10/15
  308.     dim_head = getDimData( dp );
  309.     item_num = FindDItem( dp, dp->pnLoc ) + 1;
  310.     dimmable = dim_head->dim_list;
  311.     while ( (dimmable != NULL) && (dimmable->item_num != item_num) )
  312.     {
  313.         dimmable = dimmable->next;
  314.     }
  315.     if (dimmable != NULL)
  316.     {
  317.         save_clip = NewRgn();
  318.         GetClip( save_clip );
  319.         r = dimmable->bounds;
  320.         
  321.         InsetRect(&r, -1, -1);                // so we can do 3D shading
  322.         ClipRect( &r);
  323.         
  324. #if SYSTEM_6_COMPATIBLE
  325.         if (dim_head->has_gray_text)
  326. #endif
  327.         {
  328.             if(dimmable->dim)
  329.                 TextMode( grayishTextOr );
  330.         }
  331.         if(dimmable->editable) 
  332.         {
  333.             InsetRect(&r, 1, 1);
  334.             FrameRect(&r);
  335.             
  336.             if (dim_head->has_gray_text)        // we must have colorQD
  337.             {
  338.                 if(getRectDepth(&r) > 2) {
  339.                     GetForeColor(&saveFore);    // do some subtle 3D
  340.                     RGBForeColor(&rgbA);        // shading of editText items
  341.                     
  342.                     MoveTo(r.left-1,r.bottom);
  343.                     LineTo(r.left-1,r.top-1);
  344.                     LineTo(r.right,r.top-1);
  345.                     
  346.                     ForeColor(whiteColor);
  347.                     
  348.                     Move(0,1);
  349.                     LineTo(r.right,r.bottom);
  350.                     LineTo(r.left,r.bottom);
  351.                     
  352.                     RGBForeColor(&saveFore);
  353.                 SetPenState(&save_pen);
  354.                 }
  355.             }
  356.         }
  357.         SetClip( save_clip );
  358.         DisposeRgn( save_clip );
  359.     }
  360.  
  361.     CallQDTextProc( dim_head->Old_text_proc, byteCnt, textAddr,
  362.         numerPt, denomPt );
  363.  
  364. //    GetPenState( &save_pen );                // jgs removed 10/15
  365. #if SYSTEM_6_COMPATIBLE    
  366.     if ( !dim_head->has_gray_text && (dimmable != NULL) && dimmable->dim )
  367.     {
  368.         gray_rect = dimmable->bounds;
  369.         InsetRect( &gray_rect, 1, 1 );
  370.         PenMode( patBic );
  371.         /*
  372.             The reason I used a string literal rather than the QuickDraw
  373.             global gray is so that it can be used in a code resource
  374.             without problems.
  375.         */
  376.         PenPat( (ConstPatternParam) "\x55\xAA\x55\xAA\x55\xAA\x55\xAA" );
  377.         PaintRect( &gray_rect );
  378.     }
  379. #endif
  380.     SetPenState( &save_pen );
  381. }
  382.  
  383. static short getRectDepth(Rect *r)
  384. {
  385.     Rect        gRect, iRect;
  386.     GDHandle     gDev;
  387.     short        thisDepth, pixDepth = 32;
  388.     GrafPtr        thisPort;
  389.     
  390.     GetPort(&thisPort);
  391.     if((thisPort->portBits.rowBytes & 0x8000) == 0)        // b&w port
  392.         return(1);
  393.         
  394.     gRect = *r;
  395.     
  396.     LocalToGlobal((Point *)&gRect.top);
  397.     LocalToGlobal((Point *)&gRect.bottom);
  398.     
  399.     gDev = GetDeviceList();                                // walk device list looking
  400.     while(gDev) {                                        // for lowest pixDepth
  401.         if(SectRect(&gRect, &(*gDev)->gdRect, &iRect) &&
  402.             TestDeviceAttribute(gDev,screenDevice) &&
  403.             TestDeviceAttribute(gDev,screenActive)) {
  404.             
  405.             thisDepth = (*(*gDev)->gdPMap)->pixelSize;
  406.             if(thisDepth < pixDepth)
  407.                 pixDepth = thisDepth;
  408.         }
  409.         gDev = GetNextDevice(gDev);
  410.     }
  411.     return(pixDepth);
  412. }
  413.